﻿using AutoMapper;
using Microsoft.AspNetCore.Mvc;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using web_api.DtoParameters;
using web_api.Entities;
using web_api.Helpers;
using web_api.Models;
using web_api.Services;

namespace web_api.Controllers
{
  [ApiController]
  [Route("/api/companies")]
  //[Route("api/[controller]")]
  public class CompaniesController : ControllerBase
  {
    private readonly ICompanyRepository _companyRepository;
    private readonly IMapper _mapper;
    public CompaniesController(ICompanyRepository companyRepository, IMapper mapper)
    {
      _companyRepository = companyRepository ?? throw new ArgumentNullException(nameof(companyRepository));
      _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
    }

    [HttpGet(Name =nameof(GetCompanies))]
    [HttpHead]
    public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompanies([FromQuery] CompanyDtoParameters parameters)
    {
      var compaines = await _companyRepository.GetCompaniesAsync(parameters);
      /*var companyDtos = new List<CompanyDto>();
      foreach (var company in compaines)
      {
        companyDtos.Add(new CompanyDto { Id = company.Id, Name = company.Name });
      }*/
      var previousPageLink = compaines.HasPrevious ? CreateCompaniesResourceUir(parameters, ResourceUriType.PreviousPage):null;
      var nextPageLink = compaines.HasNext ? CreateCompaniesResourceUir(parameters, ResourceUriType.NextPage):null;
      var paginationMetadata = new {
        totalCount = compaines.TotalCount,
        pageSize = compaines.PageSize,
        currentPage = compaines.CurrentPage,
        totalPages = compaines.TotalPages,
        previousPageLink,
        nextPageLink
      };
      Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(paginationMetadata,new JsonSerializerOptions {
        Encoder=JavaScriptEncoder.UnsafeRelaxedJsonEscaping
      }));
      var companyDtos = _mapper.Map<IEnumerable<CompanyDto>>(compaines);
      //return new JsonResult(compaines);
      //return NotFound();
      return Ok(companyDtos);
    }
    [HttpGet("{companyId}", Name = nameof(GetCompany))] // api/companies/123
    public async Task<ActionResult<CompanyDto>> GetCompany(Guid companyId)
    {
      /* var exist = await _companyRepository.CompanyExistsAsync(companyId);
       if (!exist)
       {
         return NotFound();
       }*/
      var company = await _companyRepository.GetCompanyAsync(companyId);
      if (company == null)
      {
        return NotFound();
      }
      return Ok(_mapper.Map<CompanyDto>(company));
    }
    [HttpPost]
    public async Task<ActionResult<CompanyDto>> CreateCompany(CompanyAddDto company)
    {
      var entity = _mapper.Map<Company>(company);
      _companyRepository.AddCompany(entity);
      await _companyRepository.SaveAsync();
      var returnDto = _mapper.Map<CompanyDto>(entity);
      return CreatedAtRoute(nameof(GetCompany), new { companyId = returnDto.Id }, returnDto);
    }
    [HttpOptions]
    public IActionResult GetCompaniesOptions() {
      Response.Headers.Add("allow", "Get,Post,Options");
      return Ok();
    }
    private string CreateCompaniesResourceUir(CompanyDtoParameters parameters, ResourceUriType type) {
      switch (type) {
        case ResourceUriType.PreviousPage:
          return Url.Link(nameof(GetCompanies), new {
            pageNumber = parameters.PageNumber - 1,
            pageSize = parameters.PageSize,
            companyName = parameters.CompanyName,
            searchTerm = parameters.SearchTerm,
          });
        case ResourceUriType.NextPage:
          return Url.Link(nameof(GetCompanies), new {
            pageNumber = parameters.PageNumber + 1,
            pageSize = parameters.PageSize,
            companyName = parameters.CompanyName,
            searchTerm = parameters.SearchTerm,
          });
        default:
          return Url.Link(nameof(GetCompanies), new {
            pageNumber = parameters.PageNumber,
            pageSize = parameters.PageSize,
            companyName = parameters.CompanyName,
            searchTerm = parameters.SearchTerm,
          });
      }
    }
    
  }
}
